package class14;

import java.util.Arrays;
import java.util.Comparator;

/**
 * 一些项目要占用一个会议室宣讲，会议室不能同时容纳两个项目的宣讲，给你每一个项目开始的时间和结束的时间
 * 你来安排宣讲的日程，要求会议室进行的宣讲的场次最多，返回最多的宣讲场次
 */
public class Code03_BestArrange {

    // 会议结构
    public static class Program {
        int start, end;

        Program(int start, int end) {
            this.start = start;
            this.end = end;
        }
    }

    // 纯暴力解法
    public static int bestArrange1(Program[] programs) {
        if (programs == null || programs.length == 0) {
            return 0;
        }
        return process(programs, 0, 0);
    }

    /**
     * 递归过程
     *
     * @param programs 会议组
     * @param count    完成的会议数
     * @param timeline 当前来到的时间点
     * @return 会议数
     */
    private static int process(Program[] programs, int count, int timeline) {
        if (programs.length == 0) {
            return count;
        }
        int max = count;
        for (int i = 0; i < programs.length; ++i) {
            if (programs[i].start >= timeline) {
                Program[] nexts = removeTimeline(programs, i);
                max = Math.max(max, process(nexts, count + 1, programs[i].end));
            }
        }
        return max;
    }

    /**
     * 删除已经抉择过的会议组
     *
     * @param programs 会议组
     * @param index    要删除的会议组
     * @return 删除后的会议组
     */
    private static Program[] removeTimeline(Program[] programs, int index) {
        Program[] nexts = new Program[programs.length - 1];
        int nextsIndex = 0;
        for (int i = 0; i < programs.length; ++i) {
            if (i != index) {
                nexts[nextsIndex++] = programs[i];
            }
        }
        return nexts;
    }

    // 贪心策略解法
    public static int bestArrange2(Program[] programs) {
        // 按照结束时间升序排序
        Arrays.sort(programs, Comparator.comparingInt(o -> o.end));
        int count = 0;
        int timeline = 0;
        for (Program program : programs) {
            if (timeline <= program.start) {
                count++;
                timeline = program.end;
            }
        }
        return count;
    }

    // for test
    public static Program[] generatePrograms(int programSize, int timeMax) {
        Program[] ans = new Program[(int) (Math.random() * (programSize + 1))];
        for (int i = 0; i < ans.length; i++) {
            int r1 = (int) (Math.random() * (timeMax + 1));
            int r2 = (int) (Math.random() * (timeMax + 1));
            if (r1 == r2) {
                ans[i] = new Program(r1, r1 + 1);
            } else {
                ans[i] = new Program(Math.min(r1, r2), Math.max(r1, r2));
            }
        }
        return ans;
    }

    public static void main(String[] args) {
        int programSize = 12;
        int timeMax = 20;
        int timeTimes = 1000000;
        for (int i = 0; i < timeTimes; i++) {
            Program[] programs = generatePrograms(programSize, timeMax);
            if (bestArrange1(programs) != bestArrange2(programs)) {
                System.out.println("Oops!");
            }
        }
        System.out.println("finish!");
    }

}
